package com.java.simple.study.jvm.gc.reference;

import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;

/**
 * @author zhoujunlin
 * @date 2021/12/18
 * @desc 演示强-软及其队列-弱引用
 * -Xmx20m -XX:+PrintGCDetails -verbose:gc
 **/
public class Demo6_1 {

    private static final int _4M = 1024 * 1024 * 4;

    public static void main(String[] args) {
        //strong(); // 结论： java.lang.OutOfMemoryError: Java heap space
        //soft(); // 结论：不会发生内存溢出 前4个被soft引用的byte数组会被回收 但是SoftReference还在占用内存
        //softQueue(); // 结论：SoftReference引用对象被回收时会进入指定队列
        weak();   // 结论：每垃圾回收 都会释放WeakReference引用的对象
    }

    public static void strong() {
        List<byte[]> list = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            list.add(new byte[_4M]);
        }
    }

    public static void soft() {
        // list -> SoftReference -> byte
        List<SoftReference<byte[]>> list = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            SoftReference<byte[]> softReference = new SoftReference<>(new byte[_4M]);
            System.out.println(softReference.get());
            list.add(softReference);
            System.out.println(list.size());
        }

        System.out.println("循环结束：" + list.size());
        list.forEach(softReference -> System.out.println(softReference.get()));
    }

    public static void softQueue() {
        // list -> SoftReference -> byte
        List<SoftReference<byte[]>> list = new ArrayList<>();
        // 引用队列
        ReferenceQueue<byte[]> referenceQueue = new ReferenceQueue<>();

        for (int i = 0; i < 5; i++) {
            // 关联引用队列 当被soft引用的byte数组被回收时 soft入队
            SoftReference<byte[]> softReference = new SoftReference<>(new byte[_4M], referenceQueue);
            System.out.println(softReference.get());
            list.add(softReference);
            System.out.println(list.size());
        }
        System.out.println("循环结束：" + list.size());
        Reference<? extends byte[]> pollObj;
        while ((pollObj = referenceQueue.poll()) != null) {
            list.remove(pollObj);
        }
        System.out.println("引用队列处理完毕：" + list.size());
        list.forEach(softReference -> System.out.println(softReference.get()));
    }

    public static void weak() {
        // list -> WeakReference -> byte
        List<WeakReference<byte[]>> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            WeakReference<byte[]> weakReference = new WeakReference<>(new byte[_4M]);
            list.add(weakReference);
            list.forEach(weakRef -> System.out.print(weakRef.get() + " "));
            System.out.println();
        }
        System.out.println("循环结束：" + list.size());
    }
}
